home *** CD-ROM | disk | FTP | other *** search
/ Joystick Magazine 1996 May / cd joy 71No13.iso / pc / demos / eurosoc / source / ballint.cpp < prev    next >
C/C++ Source or Header  |  1996-03-05  |  31KB  |  1,305 lines

  1. /******************************************************************************
  2. *******************************************************************************
  3.  
  4. Ball-Player interaction routines...
  5.  
  6. ******************************************************************************
  7. *****************************************************************************/
  8.  
  9. #include <stdio.h>
  10.  
  11. #include "audio.h"
  12.  
  13. #include "defines.h"
  14. #include "externs.h"
  15. #include "global.h"
  16. #include "data.h"
  17. #include "3deng.h"
  18.  
  19. extern capfrm *player_p;
  20. extern mcap *mcaps;
  21.  
  22. /******************************************************************************
  23. *****************************************************************************/
  24.  
  25. void out_mcball_coords()
  26. {
  27.     char str1[50];
  28.     float x,y,z;
  29.     short an,cp,frms;
  30.     char ball_in;
  31.  
  32.     for (an=0; an<117; an++)
  33.     {
  34.         frms=mcaps[an].capfrms;
  35.         ball_in=0;
  36.  
  37.         for (cp=0; cp<frms; cp++)
  38.         {
  39.             float *p=&player_p[mcaps[an].cappts+(cp)][(23*3)+1];
  40.             if (*(p+1)<0)
  41.             {
  42. // Ball not included...
  43.                 if (ball_in)
  44.                 {
  45. // Output last pos. of ball...
  46.                     sprintf(str1,"%d    Released    frms=%d    cp=%d    x=%1.3f    y=%1.3f    z=%1.3f\n",an,frms,cp,x,y,z);
  47.                     printf(str1);
  48.                     cp=frms;
  49.                 }
  50.             }
  51.             else
  52.             {
  53.                 x=*p++;
  54.                 z=*p++;
  55.                 y=-*p++;
  56.                 if (!ball_in)
  57.                 {
  58. // Contact...
  59.                     sprintf(str1,"%d    contact    frms=%d    cp=%d    x=%1.3f    y=%1.3f    z=%1.3f\n",an,frms,cp,x,y,z);
  60.                     printf(str1);
  61.                     ball_in=1;
  62.                 }
  63.             }
  64.         }
  65.  
  66.         if (!ball_in)
  67.         {
  68. // Haven't came across ball yet...
  69.             sprintf(str1,"%d    Ball not included.\n",an);
  70.             printf(str1);
  71.         }
  72.     }
  73. }
  74.  
  75. /******************************************************************************
  76. *****************************************************************************/
  77.  
  78. void get_mcball_coords(match_player *player)
  79. {
  80.     short an=player->ls_anim;
  81.     float cp=player->ls_frm;
  82.     float *p=&player_p[mcaps[an].cappts+(short)(cp*mcaps[an].capfrms)][(23*3)+1];
  83.     float z=*(p+1);
  84.     if (z>0)
  85.     {
  86.         float x=*p;
  87.         float y=-*(p+2);
  88.         float d=calc_dist(x,y);
  89.         x=x/d;
  90.         y=y/d;
  91.         ballx=player->tm_x+d*((x*player->tm_xdis)-(y*player->tm_ydis));
  92.         bally=player->tm_y+d*((y*player->tm_xdis)+(x*player->tm_ydis));
  93.         ballz=z;
  94.     }
  95.     else
  96.     {
  97.         ballx=player->tm_x;
  98.         bally=player->tm_y;
  99.         ballz=ball_diam/2;
  100.     }
  101. }
  102.  
  103. /******************************************************************************
  104. *****************************************************************************/
  105.  
  106. void user_header(match_player *player)
  107. {
  108.     float power;
  109.     if ((uf1) && (!uf2) && (in_header_rng))
  110.     {
  111.         if (um)
  112.         {
  113. // Shoot header in joystick dir.
  114.             power=(abs(angle_to_xy(ux,uy,ballxdis,ballydis)))
  115.                     *player->tm_pow/16+(MIN_HEADER_POW/16);
  116.  
  117.             ballxdis=ux*power;
  118.             ballydis=uy*power;
  119.             ballzdis=1;
  120.             new_shot(player->tm_player);
  121.             launch_ball(-1);            // Set up spin vector.
  122.         }
  123.         else
  124.         {
  125. // head in dir facing.
  126.             power=(abs(angle_to_xy(player->tm_xdis,player->tm_ydis,ballxdis,ballydis)))
  127.                     *player->tm_pow/16+(MIN_HEADER_POW/16);
  128.  
  129.             ballxdis=player->tm_xdis*power;
  130.             ballydis=player->tm_ydis*power;
  131.             ballzdis=1;
  132.             new_shot(player->tm_player);
  133.             launch_ball(1);            // Set up spin vector.
  134.         }
  135.     }
  136.  
  137.     if ((uf1) && (!uf2) && (!in_header_rng))
  138.     {
  139.         if (um)
  140.         {
  141. // punt header in joystick dir.
  142.             power=(abs(angle_to_xy(ux,uy,ballxdis,ballydis)))
  143.                     *player->tm_pow/16+(MIN_HEADER_POW/16);
  144.             ballxdis=ux*power;
  145.             ballydis=uy*power;
  146.             ballzdis=4;
  147.             launch_ball(1);            // Set up spin vector.
  148.         }
  149.         else
  150.         {
  151. // header vertical.
  152.             ballxdis=ballxdis/(player->tm_cont/16);
  153.             ballydis=ballydis/(player->tm_cont/16);
  154.             ballzdis=4+(ball_speed/(player->tm_cont/12));
  155.             launch_ball(0);            // Set up spin vector.
  156.         }
  157.     }
  158.  
  159.     if ((uf2) && (!uf1))
  160. // Header pass...
  161.     {
  162.         if (um)
  163.         {
  164. // head in joystick dir.
  165.             float x,y;
  166.             x=player->tm_xdis;
  167.             y=player->tm_ydis;
  168.             player->tm_xdis=ux;
  169.             player->tm_ydis=uy;                        // Force joystick as orientation!
  170.  
  171.             int p=pass_decide(player,in_cross_area);
  172.             make_pass(player,p,in_cross_area);
  173.  
  174.             player->tm_xdis=x;
  175.             player->tm_ydis=y;                        // Restore orientation!
  176.             launch_ball(1);            // Set up spin vector.
  177.         }
  178.         else
  179.         {
  180. // head in dir facing.
  181.             heading_ball=1;
  182.             int p=pass_decide(player,in_cross_area);
  183.             make_pass(player,p,in_cross_area);
  184.             launch_ball(1);            // Set up spin vector.
  185.         }
  186.     }
  187.  
  188.     if ((!uf1) && (!uf2))
  189.     {
  190. // Head down to grnd...
  191.         if (um)
  192.         {
  193. // downward header in joystick dir.
  194.             ballxdis=ux*(128-player->tm_cont)/16;
  195.             ballydis=uy*(128-player->tm_cont)/16;
  196.             ballzdis=-1;
  197.             launch_ball(-1);            // Set up spin vector.
  198.         }
  199.         else
  200.         {
  201. // downward header in dir facing.
  202.  
  203.             ballxdis=player->tm_xdis*(128-player->tm_cont)/16;
  204.             ballydis=player->tm_ydis*(128-player->tm_cont)/16;
  205.             ballzdis=-1;
  206.             launch_ball(-1);            // Set up spin vector.
  207.         }
  208.     }
  209.  
  210.     holder_lose_ball();
  211.     ball_inair=TRUE;
  212.      stop_ball_spin();
  213.  
  214.     init_anim(player,MC_S_HEAD);
  215.  
  216. //    float bd=calc_dist(ballxdis,ballydis);
  217. //    ballx=player->tm_x+(ballxdis*(HEADER_CONTACT+1)/bd);
  218. //    bally=player->tm_y+(ballydis*(HEADER_CONTACT+1)/bd);
  219. //    ballz=PLAYER_HEIGHT+player->tm_z;
  220.  
  221.     action="Header";
  222. }
  223.  
  224. /******************************************************************************
  225. *****************************************************************************/
  226.  
  227. void head_ball(match_player *player)
  228. {
  229.     last_touch=player->tm_player;
  230.     if (last_touch!=KP_A && last_touch!=KP_B)
  231.         pre_kp_touch=last_touch;
  232.  
  233.     reset_shot();
  234.     int p=0;
  235.     set_pos_flags(player);
  236.  
  237.     if (!player->control)
  238.         reselect();
  239.  
  240.     if (player->control)
  241.         user_header(player);
  242.     else
  243.     {
  244.         if ((keeper_a_in_box && player->tm_player==KP_A && (cannot_pick_up<1 || cannot_pick_up>11))
  245.             || (keeper_b_in_box && player->tm_player==KP_B && (cannot_pick_up<1 || cannot_pick_up<12)))
  246. // Attempt to catch ball...
  247.         {
  248.             control_ball(player);        // attempt to bring ball under control.
  249.             before=100;
  250.         }
  251.         else
  252.         {
  253.             if (!head_shoot_decide(player))
  254.             {
  255.                 if (!head_punt_decide(player))
  256.                 {
  257.                     heading_ball=1;
  258.                     if (in_cross_area)
  259.                     {
  260.                         p=(pass_decide(player,TRUE));
  261.                         if (p)
  262.                             make_pass(player,p,TRUE);
  263.                     }
  264.                     if (!p)
  265.                     {
  266. // PASS!
  267.                         p=(pass_decide(player,FALSE));
  268.                         if (p)
  269.                             make_pass(player,p,FALSE);
  270.                     }
  271.                     heading_ball=FALSE;
  272.  
  273.                     if (!p)
  274.                     {
  275.                         if (opp_around(ballx,bally,player->tm_player))
  276.                         {
  277.                             ballxdis=-ballxdis/2;
  278.                             ballydis=-ballydis/2;
  279.                             ballxdis=ballxdis+(((((float)(seed&15))-7)/16)*ball_speed);
  280.                             ballydis=ballydis+(((((float)(seed&63))-31)/64)*ball_speed);
  281.                         }
  282.                         else
  283.                         {
  284. // header vertical.
  285.                             ballxdis=ballxdis/(player->tm_cont/16);
  286.                             ballydis=ballydis/(player->tm_cont/16);
  287.                             ballzdis=4+(ball_speed/(player->tm_cont/12));
  288.                         }
  289.                     }
  290.                 }
  291.             }
  292.         }
  293.         if (before!=100)
  294. // Keeper doesn't have ball...
  295.         {
  296.             holder_lose_ball();
  297.             action="Header";
  298.         }
  299.     }
  300. }
  301.  
  302. /******************************************************************************
  303. *****************************************************************************/
  304.  
  305. void ball_at_contact(match_player *player)
  306. {
  307.     float cx,cy,cz;
  308.     rotate_offs(player->tm_anim,cx,cy,cz,player->tm_xdis,player->tm_ydis);
  309.     ballx=player->tm_x+cx;
  310.     bally=player->tm_y+cy;
  311.     ballz=player->tm_z+cz;
  312. }
  313.  
  314. /******************************************************************************
  315. *****************************************************************************/
  316.  
  317. void rebound_off_plr(match_player *player)
  318. {
  319.     penalty_shot=FALSE;
  320.     last_touch=player->tm_player;
  321.     if (last_touch!=KP_A && last_touch!=KP_B)
  322.         pre_kp_touch=last_touch;
  323.  
  324.     can_be_offside=TRUE;
  325.  
  326.     if (save_block<0)
  327.     {
  328. // Keeper block save...
  329.  
  330. // How close???
  331.         float d=SAVE_CONTACT-calc_dist(ballx-(player->tm_x+save_xoff),bally-(player->tm_y+save_yoff));
  332.  
  333.         float skill=d*player->tm_flair/(SAVE_CONTACT*128);
  334.         float bx,by;
  335.  
  336. // New ball displacement...
  337.         bx=(-(1.-skill)*ballxdis)+(skill*player->go_txdis);
  338.         by=(-(1.-skill)*ballydis)+(skill*player->go_tydis);
  339.         ballxdis=bx;
  340.         ballydis=by;
  341.  
  342.         if (ballz>SAVE_HEAD_HGT)
  343. // Up!
  344.             ballzdis=3+ballzdis*VERT_BALL_DAMP;
  345.         else
  346. // Damp!
  347.             ballzdis=ballzdis*VERT_BALL_DAMP;
  348.  
  349.         action="Rebound";
  350.         reset_shot();
  351.     }
  352.     else
  353.     {
  354.         ballxdis=-ballxdis/2;
  355.         ballydis=-ballydis/2;
  356.         ballxdis=ballxdis+(((((float)(seed&15))-7)/16)*ball_speed);
  357.         ballydis=ballydis+(((((float)(seed&63))-31)/64)*ball_speed);
  358.         float bd=calc_dist(ballxdis,ballydis);
  359.         ballx=player->tm_x+(ballxdis*(TOUCHB_BOX+1)/bd);
  360.         bally=player->tm_y+(ballydis*(TOUCHB_BOX+1)/bd);
  361.         ballzdis=ballzdis*VERT_BALL_DAMP;
  362.         action="Rebound";
  363.         reset_shot();
  364.     }
  365. }
  366.  
  367. /******************************************************************************
  368. *****************************************************************************/
  369.  
  370. void has_ball(match_player *player)
  371. {
  372.     if (comm_pass>=0 && !(seed&(32+16+8)))
  373.     {
  374.         if ((prev_touch>11 && player->tm_player>11)
  375.             || (prev_touch<12 && player->tm_player<12))
  376.         {
  377.             if (comm_pass_type==1)
  378. // Backheel...
  379.                 if (comsetp)
  380.                 {
  381.                     PlayCommentaryMessage(CP_SETPIECE);
  382.                     comsetp=0;
  383.                 }
  384.                 else
  385.                     PlayCommentaryMessage(CP_NICEMOVE);
  386.             else
  387.                 if (comm_pass_type==2)
  388. // Cross...
  389.                     if (comsetp)
  390.                     {
  391.                         PlayCommentaryMessage(CP_SETPIECE);
  392.                         comsetp=0;
  393.                     }
  394.                     else
  395.                         PlayCommentaryMessage(CP_TARGET);
  396.                 else
  397. // Normal...
  398.                 {
  399.                     float prx=teams[prev_touch-1].tm_x;
  400.                     float pry=teams[prev_touch-1].tm_y;
  401.                     float tx=player->tm_x;
  402.                     float ty=player->tm_y;
  403.                     short d=calc_dist(prx-tx,pry-ty);
  404.                     if (d>LONG_PASS_DIST)
  405.                         PlayCommentaryMessage(CP_LONG);
  406.                     else
  407.                         PlayCommentaryMessage(CP_SHORT);
  408.                 }
  409.         }
  410. /*
  411.         else
  412.         {
  413. // Not guy aimed for...
  414.             if ((prev_touch>11 && player->tm_player<12)
  415.                 || (prev_touch<12 && player->tm_player>11))
  416. // Bad pass...
  417.                 if (comm_pass || comm_pass_type==2)
  418. // Long try...
  419.                     PlayCommentaryMessage(FP_LONG);
  420.                 else
  421.                     if (comm_pass_type==1)
  422. // Backheel...
  423.                         PlayCommentaryMessage(FP_LOOSE);
  424.                     else
  425.                         PlayCommentaryMessage(FP_SHORT);
  426.         }
  427. */
  428.         comm_pass=-1;
  429.     }
  430.     else
  431.     {
  432.         if (say_names && !opponents_really_close)
  433.         {
  434.             short intone=0;
  435.             if (ball_poss<12)
  436.             {
  437.                 intone=ballx/cntspot_x;
  438.             }
  439.             else
  440.             {
  441.                 intone=(pitch_len-ballx)/cntspot_x;
  442.             }
  443.  
  444.             PlayTeamSample(real_player(ball_poss),intone);
  445.         }
  446.     }
  447. }
  448.  
  449. /******************************************************************************
  450. *****************************************************************************/
  451.     
  452. void hold_ball(match_player *player)
  453. {
  454.     if (!set_piece_on)
  455.     {
  456. // calculate position of ball at feet!
  457.         float bx,by;
  458.         bx=ballx;
  459.         by=bally;
  460.  
  461.         player->tm_poss++;
  462.         ballxdis=player->go_txdis;
  463.         ballydis=player->go_tydis;
  464.         ballzdis=0;                            // Ground ball.
  465.         ballz=ball_diam/2;
  466.  
  467.         float x=player->tm_xdis;
  468.         float y=player->tm_ydis;
  469.  
  470.         last_touch=player->tm_player;
  471.         if (last_touch!=KP_A && last_touch!=KP_B)
  472.             pre_kp_touch=last_touch;
  473.  
  474.         if (ball_in_hands)
  475.         {
  476.             if (player->tm_act==THROW_ACT)
  477.             {
  478. // Ball above player's head!
  479.                 ballz=player->tm_z+(PLAYER_HEIGHT+4);
  480.                 ballx=player->tm_x;
  481.                 bally=player->tm_y;
  482.                 ball_in_hands=TRUE;
  483.             }
  484.             else
  485.             {
  486.                 if (player->int_move!=I_GET_UP || !player->int_cnt)
  487.                 {
  488.                     if (player->tm_act==SAVE_ACT)
  489.                     {
  490.                         ballz=player->tm_z+save_zoff;
  491.                         ballx=player->tm_x+save_xoff;
  492.                         bally=player->tm_y+save_yoff;
  493.                         player->dir_mode=5;
  494.                     }
  495.                     else
  496.                     {
  497.                         ballz=player->tm_z+(PLAYER_HEIGHT/2);
  498.                         ballx=player->tm_x+(x*IN_HANDS_DIST);
  499.                         bally=player->tm_y+(y*IN_HANDS_DIST);
  500.                         if (player->tm_act!=KPHOLD_ACT)
  501.                             player->dir_mode=2;
  502.                         else
  503.                             player->dir_mode=3;
  504.                     }
  505.                 }
  506.             }
  507.         }
  508.         else
  509.         {
  510.             if (player->tm_poss==HAS_BALL_DELAY)
  511.                 has_ball(player);
  512.  
  513. //            inc_poss(player->tm_player);
  514.             double n;
  515.             player->dir_mode=0;
  516.             ball_inair=FALSE;
  517.             if (player->tm_act==RUN_ACT)
  518.             {
  519.                 bx=player->tm_x+(x*(AT_FEET_DIST+(4.*(modf(player->tm_frm,&n)-.5))));
  520.                 by=player->tm_y+(y*(AT_FEET_DIST+(4.*(modf(player->tm_frm,&n)-.5))));
  521.             }
  522.             else
  523.             {
  524.                 if (!dead_ball_cnt)
  525.                 {
  526. // If player is in a set-piece then no need to move position of ball...
  527.                     bx=player->tm_x+(x*AT_FEET_DIST);
  528.                     by=player->tm_y+(y*AT_FEET_DIST);
  529.                 }
  530.             }
  531.  
  532.             if (player->tm_ftime<-1)
  533.             {
  534. // Just controlled ball... (so tween to held pos.)
  535. // ftime (-2 to -10)...
  536.                 if (player->tm_ftime==-2)
  537.                     get_mcball_coords(player);
  538.                 else
  539.                 {
  540.                     ballx+=((bx-ballx)*(-2-player->tm_ftime)/8);
  541.                     bally+=((by-bally)*(-2-player->tm_ftime)/8);
  542.                 }
  543. //                ballx=bx;
  544. //                bally=by;
  545.                 if (--player->tm_ftime==-11)
  546.                     player->tm_ftime=0;
  547.             }
  548.             else
  549.             {
  550. // No tweening...
  551.                 ballx=bx;
  552.                 bally=by;
  553.             }
  554.         }
  555.  
  556.         if (((player->tm_player==KP_A) || (player->tm_player==KP_B))
  557.             && (player->tm_act==STAND_ACT) && (ball_in_hands))
  558.             init_kphold_act(player);
  559.     }
  560.     else
  561.     {
  562.         last_touch=player->tm_player;
  563.         if (last_touch!=KP_A && last_touch!=KP_B)
  564.             pre_kp_touch=last_touch;
  565.     }
  566. }
  567.  
  568. /******************************************************************************
  569. *****************************************************************************/
  570.  
  571. void init_specials()
  572. {
  573.     spec_kick_type=0;
  574.     f1_down=FALSE;
  575.     f2_down=FALSE;
  576. }
  577.  
  578. /******************************************************************************
  579. *****************************************************************************/
  580.  
  581. void collect_ball(match_player *player)
  582. {
  583.     add_comp_pass(player->tm_player);
  584.     if (player->tm_act==TACKLE_ACT)
  585.         inc_twon(player->tm_player);
  586.  
  587.     if (!player->tm_leave)
  588.         reset_leaves();
  589.  
  590. //    comm_pass=-1;        //FIX
  591.     prev_touch=last_touch;
  592.     receiver_a=FALSE;
  593.     receiver_b=FALSE;
  594.     init_specials();
  595.  
  596.     if ((must_shoot) || (must_punt) || (must_pass))
  597.     {
  598.         must_shoot=-must_shoot;
  599.         must_pass=-must_pass;
  600.         must_punt=-must_punt;
  601.     }
  602.  
  603.     if ((player->tm_player!=KP_A) && (player->tm_player!=KP_B))
  604.         cannot_pick_up=player->tm_player;
  605.  
  606. // Keeper can pick up ball...
  607.  
  608.     hold_ball(player);
  609.     if ((ball_in_hands) && (player->tm_act!=SAVE_ACT))
  610.         reset_all_ideas();
  611.     stop_ball_spin();
  612.     ball_poss=player->tm_player;
  613.     player->tm_poss=1;
  614.     if ((player->int_cnt) && (player->int_move==I_INTERCEPT))
  615.         reset_ideas(player);
  616.     action="Collect";
  617.     reset_shot();
  618.     penalty_shot=FALSE;
  619.  
  620.     if (player->tm_act==CONTROL_ACT)
  621.         ball_at_contact(player);
  622.  
  623.     reselect();
  624. }
  625.  
  626. /******************************************************************************
  627. *****************************************************************************/
  628.  
  629. void control_difficulty(match_player *player)
  630.  
  631. // Calculates difficulty factor (0 simple -> 128 impossible)!
  632. {
  633.     float x=ballx-ballxdis;        //take ball one step back!
  634.     float y=bally-ballydis;
  635.     x=x-player->tm_x;                //offset to player.
  636.     y=y-player->tm_y;
  637.     int cside=get_dir(x,y);        //contact side of player.
  638.     cside=cside-player->face_dir;
  639.     if (cside<0)
  640.         cside=cside+8;
  641.     if (cside>4)
  642.         cside=8-cside;
  643.     difficulty=cside*16;            //direction difficulty!
  644.     int s=ball_speed*2;
  645.  
  646.     if (player->tm_act==RUN_ACT)
  647.         if (want_pass==player->tm_player)
  648. // He is expecting it so better chance of controlling ball!
  649.             s+=2;
  650.         else
  651.             s+=4;                            // speed factor.
  652.  
  653.     if (player->tm_act==TACKLE_ACT)
  654.         s+=8;                            // speed factor.
  655.     if ((player->tm_act==SAVE_ACT) || (((player->tm_player==KP_A) || (player->tm_player==KP_B))
  656.         && (ballz>PLAYER_HEIGHT/3)))
  657.         s-=4;                            // Keeper saving!
  658.  
  659.     difficulty+=(6*s);                //add speed difficulty!
  660. }
  661.  
  662. /******************************************************************************
  663. *****************************************************************************/
  664.  
  665. void active_control(match_player *player)
  666. {
  667.     if (player->tm_ftime>=0)
  668.     {
  669.         float cx,cy,cz;
  670.         rotate_offs(player->tm_anim,cx,cy,cz,player->tm_xdis,player->tm_ydis);
  671.         ballx=player->tm_x+cx;
  672.         bally=player->tm_y+cy;
  673.         ballz=player->tm_z+cz;
  674.         ballxdis=player->tm_xdis*(2+(ball_speed/(player->tm_cont/32)));
  675.         ballydis=player->tm_ydis*(2+(ball_speed/(player->tm_cont/32)));
  676.         ballzdis=1;
  677.         last_touch=player->tm_player;
  678.         if (last_touch!=KP_A && last_touch!=KP_B)
  679.             pre_kp_touch=last_touch;
  680.         player->tm_ftime=-1;                // Continue animation!
  681.     }
  682. }
  683.  
  684. /******************************************************************************
  685. *****************************************************************************/
  686.  
  687. void standard_fstep(match_player *player)
  688. {
  689.     switch(player->tm_anim)
  690.     {
  691.         case(MC_D_HEAD):
  692.             player->tm_fstep=MC_D_HEAD_FS;
  693.             break;
  694.  
  695.         case(MC_CHEST):
  696.             player->tm_fstep=MC_CHEST_FS;
  697.             break;
  698.  
  699.         case(MC_TRAPL):
  700.         case(MC_TRAPR):
  701.             player->tm_fstep=MC_TRAP_FS;
  702.             break;
  703.  
  704.         case(MC_SHOOTL):
  705.         case(MC_SHOOTR):
  706.             player->tm_fstep=MC_SHOOT_FS;
  707.             break;
  708.  
  709.         case(MC_CHIPL):
  710.         case(MC_CHIPR):
  711.             player->tm_fstep=MC_CHIP_FS;
  712.             break;
  713.  
  714.         case(MC_VOLLEYL):
  715.         case(MC_VOLLEYR):
  716.             player->tm_fstep=MC_VOLLEY_FS;
  717.             break;
  718.  
  719.         case(MC_OVERHEAD):
  720.             player->tm_fstep=MC_OVERHEAD_FS;
  721.             break;
  722.  
  723.         case(MC_DV_HEAD):
  724.             player->tm_fstep=MC_DV_HEAD_FS;
  725.             break;
  726.  
  727.         case(MC_S_HEAD):
  728.             player->tm_fstep=MC_S_HEAD_FS;
  729.             break;
  730.  
  731.         case(MC_J_HEAD):
  732.             player->tm_fstep=MC_J_HEAD_FS;
  733.             break;
  734.  
  735.     }
  736. }
  737.  
  738. /******************************************************************************
  739. *****************************************************************************/
  740.  
  741. void control_ball(match_player *player)
  742.  
  743. // Having made contact with ball,
  744. // the player must attempt to control it!
  745.  
  746. {
  747.     can_be_offside=TRUE;
  748.  
  749.     if (player->tm_act==CONTROL_ACT)
  750.     {
  751. // Player has successfully controlled ball.
  752.         if (player->tm_anim==MC_U_HEAD)
  753. // Head Control...(Bounce ball upward!)
  754.         {
  755.             active_control(player);
  756.         }
  757.         else
  758.         {
  759.  
  760.             holder_lose_ball();
  761.             collect_ball(player);        //bring ball to feet!
  762.             player->dir_mode=2;
  763.             if (player->tm_anim!=MC_TRAPL && player->tm_anim!=MC_TRAPR)
  764.             {
  765.                 standard_fstep(player);        // Normal speed anim...
  766.                 ball_limbo(player->tm_player,1-player->tm_fstep);        // Ball is motion captured to ground!
  767.             }
  768.         }
  769.     }
  770.     else
  771.     {
  772.         if (player->tm_act==TACKLE_ACT)
  773.             player->go_step=TRUE;                // He has touched the ball (no foul)!
  774.         control_difficulty(player);
  775.         if ((((player->tm_act!=SAVE_ACT) && (player->tm_z<1))
  776.             || ((player->tm_act==SAVE_ACT) || (player->tm_player==KP_A)    
  777.             || (player->tm_player==KP_B) && (player->tm_z>PLAYER_HEIGHT/3)))
  778.             && (seed+player->tm_cont>difficulty))
  779.         {
  780. // Assume controlled ball is at feet level.
  781.             holder_lose_ball();
  782.             collect_ball(player);        //bring ball to feet!
  783.         }
  784.         else
  785.             rebound_off_plr(player);        //could not control!
  786.     }
  787. }
  788.  
  789. /******************************************************************************
  790. *****************************************************************************/
  791.  
  792. char control_interact(match_player *player)
  793. {
  794.     if (player->tm_frm>=player->contact)
  795.     {
  796. // Contact point exceeded...
  797.  
  798.         if (player->tm_anim!=MC_TRAPL && player->tm_anim!=MC_TRAPR)
  799.         {
  800.             player->tm_anim++;
  801.             player->tm_anim--;
  802.         }
  803.  
  804.         float px=player->tm_x;
  805.         float py=player->tm_y;
  806.         float pz=player->tm_z;
  807.  
  808.         float cx,cy,cz;
  809.         rotate_offs(player->tm_anim,cx,cy,cz,player->tm_xdis,player->tm_ydis);
  810.         
  811.         px+=cx;
  812.         py+=cy;
  813.         pz+=cz;
  814.  
  815.         float d=calc_dist(ballx-px,bally-py);
  816.         if (d>ball_speed+2 && d>8)
  817.             return(FALSE);
  818.  
  819.         if    (abs(ballz-pz)>prat/2)
  820.             return(FALSE);
  821.     
  822. // Good contact... (control ball)!
  823.           return(TRUE);
  824.     }
  825.     return(FALSE);
  826. }
  827.  
  828. /******************************************************************************
  829. *****************************************************************************/
  830.  
  831. void ball_interact(match_player *player)
  832. {
  833.     int act=player->tm_act;
  834.  
  835.     if (player->tm_poss<=0)
  836.     {
  837.         player->tm_poss=0;
  838.         if (!((act==FALL_ACT) ||
  839.             (act==RISE_ACT) || (act==RIDE_ACT) || (dead_ball_cnt)))    //player not out of game.
  840.         {
  841.             if ((!((player->int_cnt!=0) && (player->int_move==I_KICKED)))
  842.                 && (!ball_in_hands))
  843.             {
  844.                 if (act!=SAVE_ACT)
  845.                 {
  846. // Normal player...
  847.                     if (!just_scored && ((!ball_poss) || (ball_poss && teams[ball_poss-1].tm_act!=PICKUP_ACT)))
  848.                     {
  849.  
  850.                     if (!ball_poss || (ball_poss && ball_poss<12 && player->tm_player>11)
  851.                         || (ball_poss>11 && player->tm_player<12))
  852.                     {
  853. // Ball is free or the opponent has ball...
  854.  
  855.                         if (act==CONTROL_ACT && player->tm_ftime>=0 && control_interact(player))
  856.                         {
  857. // He has successfully controlled the ball!
  858.                             control_ball(player);
  859.                         }
  860.  
  861.                         if (act==STRIKE_ACT && player->tm_ftime>=0 && control_interact(player))
  862.                         {
  863. // He has successfully struck the ball!
  864.                             strike_ball_off(player);
  865.                         }
  866.  
  867.                         if (player->tm_act!=CONTROL_ACT && player->tm_act!=STRIKE_ACT)
  868.                         {
  869.                             if (!player->tm_strike && TOUCHB_BOX>=calc_dist(ballx-player->tm_x,bally-player->tm_y)
  870.                                  && ballz<PLAYER_HEIGHT && (!penalty_game || player->tm_player==KP_A || player->tm_player==KP_B))
  871.                             {
  872. // Contact is made...
  873.                                 receiver_a=FALSE;
  874.                                 receiver_b=FALSE;
  875.  
  876.                                 if (!practice && (player->tm_leave>0) && (last_touch==player->tm_player))
  877.                                 {
  878.                                     init_foul(player->tm_player,FALSE,TRUE);    // Indirect F.K. for touching ball again!
  879.                                 }
  880.  
  881.                                 if ((ballz<player->tm_z+PLAYER_HEIGHT/2)
  882.                                     && (ballz-ballzdis<player->tm_z+PLAYER_HEIGHT/2))
  883.                                 {
  884. //Contact with ball at feet...
  885.                                     if (act<=TURN_ACT || act==TACKLE_ACT || act==STEAL_ACT)
  886.                                         control_ball(player);
  887.                                 }
  888.                                 else
  889.                                 {
  890.                                     if (ballz<player->tm_z+PLAYER_HEIGHT-3)
  891.                                     {
  892. // At head and body height...
  893.                                         if (act<=TURN_ACT || act==TACKLE_ACT || act==STEAL_ACT)
  894.                                             rebound_off_plr(player);
  895.                                     }
  896.                                 }
  897.                             }
  898.                         }
  899.                     }
  900.                     }
  901.  
  902.                     if (player->tm_leave<0)
  903.                         player->tm_leave=TRUE;
  904.                 }
  905.                 else
  906.                 {
  907. // Keeper save!
  908.                     if (player->tm_frm>(keeper_contact-0.00001))
  909.                     {
  910. // Contact with ball reached...
  911.                         if (keeper_will_save>0 || keep_dive)
  912.                         {
  913. // Keeper should connect with ball at contact point...
  914.                             if (keep_dive || (SAVE_CONTACT>calc_dist(ballx-(player->tm_x+save_xoff),bally-(player->tm_y+save_yoff))
  915.                                  && !ball_in_goal))
  916. // Keeper has judged it well!
  917.                             {
  918.                                 inc_saves(player->tm_player);
  919.                                 shot_saved=25;
  920.                                 keeper_will_save=-1;
  921.                                 if (save_block && !keep_dive)
  922.                                 {
  923.                                     if (real_shot)
  924.                                     {
  925.                                         PlayCommentaryMessage(PM_BLOCK);
  926.                                         inc_save(last_touch);
  927.                                     }
  928.                                     save_block=-1;                        // Rebound properly from block!
  929.                                     rebound_off_plr(player);        //could not control!
  930.                                     ball_inair=TRUE;
  931.                                     ballz=save_zoff;
  932.                                     ballx=player->tm_x+player->go_txdis+save_xoff;
  933.                                     bally=player->tm_y+player->go_tydis+save_yoff;
  934.                                     save_block=0;                        // Rebound properly from block!
  935.                                 }
  936.                                 else
  937.                                 {
  938.                                     if (real_shot)
  939.                                     {
  940.                                         PlayCommentaryMessage(PM_CATCH);
  941.                                         inc_save(last_touch);
  942.                                     }
  943.                                     holder_lose_ball();
  944.                                     ball_in_hands=TRUE;
  945.                                     collect_ball(player);        //bring ball to feet!
  946.                                 }
  947.                                 keep_dive=FALSE;
  948.                             }
  949.                             else
  950.                             {
  951. // Ball too far!!!
  952.                                 keeper_will_save=0;        // Catch will change to block...
  953.                                 if (!save_block)
  954.                                 {
  955. // Must become desperate block instead of catch...
  956.                                     if (ABS(player->tm_anim)<MC_BFOOTBL)
  957.                                     {
  958. // Zone A save...(no right,left)
  959.                                         player->tm_anim--;
  960.                                     }
  961.                                     else
  962.                                     {
  963.                                         player->tm_anim-=2;
  964.                                     }
  965.  
  966.                                     player->go_cnt=(1-player->tm_frm)/player->tm_fstep;
  967.  
  968.                                     if (!player->tm_anim)        // AFOOTB
  969.                                         keeper_on_grnd=FALSE;
  970.                                     
  971.                                     if (keeper_on_grnd)
  972.                                         player->int_cnt=player->go_cnt+2;
  973.                                     else
  974.                                         player->int_cnt=player->go_cnt+2;
  975.                                 }
  976.                             }
  977.                         }
  978.                     }
  979.                 }
  980.             }
  981.         }
  982.     }
  983.     else
  984.     {
  985.         if ((player->contact>0) && (player->tm_act==KICK_ACT))
  986.         {
  987. // Currently awaiting contact point in animation...
  988. // He's kicking the ball just now...
  989.  
  990.             ballx+=((player->tm_x+b_xoff)-ballx)*player->tm_frm/player->contact;
  991.             bally+=((player->tm_y+b_yoff)-bally)*player->tm_frm/player->contact;
  992.             ballz+=((player->tm_z+b_zoff)-ballz)*player->tm_frm/player->contact;
  993.  
  994.         }
  995.         else
  996.         {
  997.             if (((ballz>=player->tm_z) && (ballz<PLAYER_HEIGHT+player->tm_z))
  998.                 || (act==THROW_ACT) || (act==SAVE_ACT) || (act=KPHOLD_ACT))
  999.             {
  1000.                 if (player->tm_player==ball_poss)
  1001.                     hold_ball(player);
  1002.                 else
  1003.                     player->tm_poss=0;                // doesnt have ball any more.
  1004.             }
  1005.             else
  1006.             {
  1007.                 holder_lose_ball();
  1008.             }
  1009.         }
  1010.     }
  1011. }
  1012.  
  1013. /******************************************************************************
  1014. *****************************************************************************/
  1015.  
  1016. // Predicts ball coords from now till 50 turns ahead!
  1017.  
  1018. void predict_ball()
  1019. {
  1020.     struct stack{
  1021.         float x; float y; float z;
  1022.         float xd; float yd; float zd;
  1023.         int ba; int bs; int sw; float xys; float zs;
  1024.         float f_xys; float f_zs; int sp_b;};
  1025.  
  1026.     struct stack sp;
  1027.  
  1028.     sp.x=ballx;
  1029.     sp.y=bally;
  1030.     sp.z=ballz;
  1031.     sp.xd=ballxdis;
  1032.     sp.yd=ballydis;
  1033.     sp.zd=ballzdis;
  1034.     sp.ba=ball_inair;
  1035.     sp.bs=ball_still;
  1036.     sp.sw=swerve;
  1037.     sp.xys=ball_xyspin;
  1038.     sp.zs=ball_zspin;
  1039.     sp.f_xys=full_xyspin;
  1040.     sp.f_zs=full_zspin;
  1041.     sp.sp_b=spin_cnt;
  1042.  
  1043.     ns_ballx=ballx;
  1044.     ns_bally=bally;
  1045.     ns_ballz=ballz;
  1046.  
  1047.     float *ptr1=&ball_pred_tab[0][0];
  1048.     float *ptr2=&ns_ball_pred_tab[0][0];
  1049.  
  1050.     first_bounce=-1;
  1051.     prediction=TRUE;
  1052.     for (int i=0; i<50; i++)
  1053.     {
  1054. // Ball with swerve!
  1055.         *ptr1++=ballx;
  1056.         *ptr1++=bally;
  1057.         *ptr1++=ballz;
  1058.         if (first_bounce<0 && ballz<=(ball_diam/2) && i>0)
  1059.             first_bounce=i;
  1060.  
  1061. // Ball without swerve!
  1062.         *ptr2++=ns_ballx;
  1063.         *ptr2++=ns_bally;
  1064.         *ptr2++=ns_ballz;
  1065.  
  1066.         if (!ball_poss)
  1067.             ball_trajectory();
  1068.         else
  1069.         {
  1070.             if (teams[ball_poss-1].tm_act==TACKLE_ACT)
  1071.             {
  1072. // Take into account deceleration of tackle action!
  1073.                 ballx+=ballxdis*pow(TACKLE_DECEL,i);
  1074.                 bally+=ballydis*pow(TACKLE_DECEL,i);
  1075.                 ns_ballx+=ballxdis*pow(TACKLE_DECEL,i);
  1076.                 ns_bally+=ballydis*pow(TACKLE_DECEL,i);
  1077.             }
  1078.             else
  1079.             {
  1080.                 ballx+=ballxdis;
  1081.                 bally+=ballydis;
  1082.                 ns_ballx+=ballxdis;
  1083.                 ns_bally+=ballydis;
  1084.             }
  1085.         }
  1086.     }
  1087.  
  1088.     spin_cnt=sp.sp_b;
  1089.     full_zspin=sp.f_zs;
  1090.     full_xyspin=sp.f_xys;
  1091.     ball_zspin=sp.zs;
  1092.     ball_xyspin=sp.xys;
  1093.     swerve=sp.sw;
  1094.     ball_still=sp.bs;
  1095.     ball_inair=sp.ba;
  1096.     ballzdis=sp.zd;
  1097.     ballydis=sp.yd;
  1098.     ballxdis=sp.xd;
  1099.     ballz=sp.z;
  1100.     bally=sp.y;
  1101.     ballx=sp.x;
  1102. }
  1103.  
  1104. /******************************************************************************
  1105. *****************************************************************************/
  1106.  
  1107. // Find no. of opponents near ball holder.
  1108.  
  1109. void get_opp_near_ball(int holder)
  1110. {
  1111.     opponents_near_holder=0;            // Initialise count.
  1112.     opponents_really_close=0;
  1113.     int p;
  1114.     if (holder)
  1115.     {
  1116.         if (holder>11)                        // Get opposing team.
  1117.             p=0;
  1118.         else
  1119.             p=11;
  1120.         for (int i=p; i<p+11; i++)
  1121.         {
  1122.             if ((teams[i].guy_on>0) && (teams[i].tm_dist<=DRIB_DANGER_AREA))
  1123.             {
  1124.                 opponents_near_holder++;
  1125.                 if (teams[i].tm_dist<=MEGA_DANGER_AREA)
  1126.                     opponents_really_close++;
  1127.             }
  1128.         }
  1129.     }
  1130. }
  1131.  
  1132. /******************************************************************************
  1133. *****************************************************************************/
  1134.  
  1135. void get_dist_pos(int pn)
  1136. {
  1137.     float d,lowest;
  1138.     int guy=pn;
  1139.  
  1140.     for (int pos=2; pos<5; pos++)
  1141.     {
  1142.         lowest=2000;
  1143.  
  1144.         for (int i=pn; i<pn+12; i++)
  1145.         {
  1146.             if (teams[i-1].guy_on>0)
  1147.             {
  1148.                 d=teams[i-1].tm_dist;
  1149.                 if ((d<lowest) && (!teams[i-1].tm_pos))
  1150.                 {
  1151.                     guy=i;
  1152.                     lowest=d;
  1153.                 }
  1154.             }
  1155.         }
  1156.         teams[guy-1].tm_pos=pos;
  1157.     }
  1158. }
  1159.  
  1160. /******************************************************************************
  1161. *****************************************************************************/
  1162.  
  1163. // Updates player distances.
  1164.  
  1165. #define SELECTION_CIRCLE (prat*10)
  1166.  
  1167. void player_distances()
  1168. {
  1169.     float px,py;
  1170.     float ad=2000;
  1171.     float bd=2000;
  1172.     float d;
  1173.     defense_a=cntspot_x;
  1174.     defense_b=cntspot_x;
  1175.  
  1176.     for (player_num=0; player_num<players; player_num++)
  1177.     {
  1178.         if (teams[player_num].guy_on>0)
  1179.         {
  1180.             px=teams[player_num].tm_x;
  1181.  
  1182.             if (player_num<11)
  1183.             {
  1184.                 if (px<defense_a && player_num)
  1185.                     defense_a=px;
  1186.  
  1187.                  d=calc_dist(pitch_len-teams[player_num].tm_x,cntspot_y-teams[player_num].tm_y);
  1188.  
  1189.                 if (d<(MIN_SHOOT_DIST+((float)teams[player_num].tm_pow*3)))
  1190.                     teams[player_num].tm_srng=TRUE;
  1191.                 else
  1192.                     teams[player_num].tm_srng=FALSE;
  1193.             }
  1194.             else
  1195.             {
  1196.                 if  ((player_num!=11) && (px>defense_b))
  1197.                     defense_b=px;
  1198.  
  1199.                 d=calc_dist(teams[player_num].tm_x,cntspot_y-teams[player_num].tm_y);
  1200.  
  1201.                 if (d<(MIN_SHOOT_DIST+((float)teams[player_num].tm_pow*3)))
  1202.                     teams[player_num].tm_srng=TRUE;
  1203.                 else
  1204.                     teams[player_num].tm_srng=FALSE;
  1205.             }
  1206.  
  1207.             px-=ballx;
  1208.             py=teams[player_num].tm_y-bally;
  1209.             d=calc_dist(px,py);
  1210.             teams[player_num].tm_dist=d;
  1211.             teams[player_num].tm_pos=0;
  1212.             if (player_num>=players/2)
  1213.             {
  1214.                 if (d<bd)
  1215.                 {
  1216.                     bd=d;
  1217.                     nearest_b=player_num+1;
  1218.                 }
  1219.             }
  1220.             else
  1221.             {
  1222.                 if (d<ad)
  1223.                 {
  1224.                     ad=d;
  1225.                     nearest_a=player_num+1;
  1226.                 }
  1227.             }
  1228.             if (player_num!=(KP_A-1) && player_num!=(KP_B-1))
  1229.                 sel_circle[player_num]=(d<SELECTION_CIRCLE ? TRUE:FALSE);
  1230.             else
  1231.                 sel_circle[player_num]=FALSE;
  1232.         }
  1233.     }
  1234.     teams[nearest_a-1].tm_pos=1;
  1235.     teams[nearest_b-1].tm_pos=1;
  1236.     get_dist_pos(1);
  1237.     get_dist_pos(12);
  1238. }
  1239.  
  1240. /******************************************************************************
  1241. *****************************************************************************/
  1242.  
  1243. // Return closest guy to the ball (from one team) who is not busy!
  1244. // p_num = first player in team.
  1245.  
  1246. int get_nearest_guy(int p_num)
  1247. {
  1248.     int near_guy=0, closest=10000;
  1249.     for (int i=p_num; i<p_num+11; i++)
  1250.     {
  1251.         if (teams[i].tm_act<=TURN_ACT)                //player is not busy!
  1252.         {
  1253.             if (teams[i].tm_dist<closest)
  1254.             {
  1255.                 near_guy=i+1;                        //This guy is closer!
  1256.                 closest=teams[i].tm_dist;
  1257.             }
  1258.         }
  1259.     }
  1260.     return(near_guy);
  1261. }
  1262.  
  1263. /******************************************************************************
  1264. *****************************************************************************/
  1265.  
  1266. void get_nearest()
  1267. {
  1268.     if (receiver_a)
  1269.         near_path_a=receiver_a;
  1270.     else
  1271.         near_path_a=get_near_path(0,TRUE);
  1272.  
  1273.     if (receiver_b)
  1274.         near_path_b=receiver_b;
  1275.     else
  1276.         near_path_b=get_near_path(11,TRUE);
  1277. }
  1278.  
  1279. /******************************************************************************
  1280. *****************************************************************************/
  1281.  
  1282. void holder_lose_ball()
  1283. {
  1284.     if (ball_poss)
  1285.     {
  1286.         reset_ideas(&teams[ball_poss-1]);
  1287.         if (ball_poss<12)
  1288.             ball_released=OFFSIDE_REL_CNT;
  1289.         else
  1290.             ball_released=-OFFSIDE_REL_CNT;
  1291.  
  1292.         short p=teams[ball_poss-1].tm_poss;
  1293.         teams[ball_poss-1].tm_posst+=p*p/50;    // Good dribbles will adjust performance.
  1294.         teams[ball_poss-1].tm_poss=0;
  1295.         ball_poss=0;
  1296.         in_cross_area=FALSE;
  1297.         ball_in_hands=FALSE;
  1298.         must_punt=FALSE;
  1299.         must_pass=FALSE;
  1300.         must_shoot=FALSE;
  1301.     }
  1302. }
  1303.  
  1304.  
  1305.